#include <cstdlib>
#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fstream>
#include <ctime>
#include <sstream>
#include <list>
#include <vector>
#include <nlohmann/json.hpp>
#include <csignal>
#include <thread>
#include <chrono>       // 新增头文件
#include <mutex>        // 新增头文件
#include "../Converter/voicapi.h"
#include "../Gpt/gptapi.h"

#define SESSION_TOKEN "53d4e4e3-55c8-4fb8-9e98-96be19d2a6de"
#define MODEL_NAME "qwen-plus-latest"
#define SYSTEM_CONTENT "需要你扮演一名优秀的设备助手，你的名字叫小爱。确保满足用户日常友好交流需求，做用户的好朋友。情绪判断存疑时询问确认，所有回复保持口语化，单句最好控制在20-30字内，特殊情况可详细回复，扮演一名耐心倾听的好朋友，通过用词节奏传递温暖感，确保语音合成后流畅自然。\
                            注：用户情绪为摄像头捕捉到用户面部表情图片识别出来的情绪结果，识别准确率并不是非常精确但具有一定参考意义，所以要结合用户对话合理判断用户需求并结合上述要求给出合理反馈，呼吸心跳数据为捕获到的用户每分钟呼吸心跳频率"
#define ACTIVE_EMOTION_PATH "../Emotional/active_emotion"
#define PHYSIO_DATA "../data.txt"  // 生理数据文件路径
#define CHAT_HISTORY_SIZE 30
#define EMOTION_CHANGE_CHECK_TIME 15
#define EMOTION_ALERTS_SIZE 30
#define ACTIVE_EMOTION_PATH "../Emotional/active_emotion"

using namespace std;
using json = nlohmann::json;

// 服务器名称
const string SERVER_NAME = "Server: Web Server 1.0 - BooLo\r\n";
string breathStr = "30", heartbeatStr = "70";

// 语音转文字，文字转语言接口
Vtz::VoiceToChinese vtz;
// gpt接口
Gpt::ChatWithGpt chat;

// 定义消息结构体
struct Message {
    string text;
    string time;
    string emotion;
};

// 全局变量：存储聊天记录。每次最多保留20条消息
std::list<Message> chatHistory;

// 新增全局变量（情绪监控相关）
std::vector<json> emotionAlerts;      // 情绪变化记录
std::string lastEmotion = "";         // 上次记录的情绪
std::mutex emotionMutex;              // 线程安全锁
bool isMonitoring = true;             // 监控状态标志

// 新增：生理数据相关全局变量
std::mutex physioDataMutex;           // 生理数据文件访问锁
bool isPhysioUpdateRunning = true;    // 生理数据更新线程运行标志

// 初始化服务器套接字
int ServerSocketInit(int port) {
    int serverSock = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSock < 0) {
        perror("Failed to create socket!");
        exit(1);
    }

    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    serverAddr.sin_addr.s_addr = inet_addr("0.0.0.0");

    if (bind(serverSock, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        perror("Failed to bind stream socket!");
        exit(1);
    }

    return serverSock;
}

// 获取文件类型对应的MIME类型
string GetContentType(const string& uri) {
    size_t dotPos = uri.rfind('.');
    if (dotPos != string::npos) {
        string suffix = uri.substr(dotPos + 1);
        if (suffix == "html") return "Content-type: text/html\r\n";
        if (suffix == "jpg") return "Content-type: image/jpeg\r\n";
        if (suffix == "png") return "Content-type: image/png\r\n";
        if (suffix == "gif") return "Content-type: image/gif\r\n";
        if (suffix == "txt") return "Content-type: text/plain\r\n";
        if (suffix == "xml") return "Content-type: text/xml\r\n";
        if (suffix == "rtf") return "Content-type: text/rtf\r\n";
        if (suffix == "js") return "Content-type: application/javascript\r\n";
        if (suffix == "css") return "Content-type: text/css\r\n";
        if (suffix == "mp3") return "Content-Type: audio/mpeg\r\n";
    }
    return "Content-type: application/octet-stream\r\n";
}

// 获取当前系统时间
string GetCurrentTime() {
    time_t now = time(0);
    char* dt = ctime(&now);
    return string(dt);
}

// 发送响应到客户端
bool SendResponse(int socket, const string& response) {
    size_t sent = 0;
    while (sent < response.size()) {
        int rval = send(socket, &response.data()[sent], response.size() - sent, 0);
        if (rval < 0) return false;
        sent += rval;
    }
    return true;
}

// 处理客户端请求的函数
bool HandleRequest(int socket);

// 处理POST请求的函数
bool HandlePostRequest(string uri);

// 处理GET getMessages请求的函数
bool HandleGetMessagesRequest(int socket);

// 新增：处理情绪告警请求
bool HandleGetEmotionAlerts(int socket);

// 用户与GPT聊天的函数
void UserChatWithGpt();

string GetEmotion();

// 新增：生成随机生理数据
void GenerateRandomPhysioData(int& breath, int& heartbeat) {
    // 呼吸频率正常范围：12-20次/分钟
    breath = rand() % 9 + 12;  // 12-20
    // 心跳频率正常范围：60-100次/分钟
    heartbeat = rand() % 41 + 60;  // 60-100
}

// 新增：更新生理数据到文件
void UpdatePhysioDataToFile() {
    srand(time(0));  // 初始化随机种子
    
    while (isPhysioUpdateRunning) {
        // 生成随机数据
        int breath, heartbeat;
        GenerateRandomPhysioData(breath, heartbeat);
        
        // 写入文件
        {
            std::lock_guard<std::mutex> lock(physioDataMutex);  // 自动加锁解锁
            ofstream dataFile(PHYSIO_DATA);
            if (dataFile.is_open()) {
                dataFile << breath << endl << heartbeat;
                dataFile.close();
                cout << "更新生理数据: 呼吸=" << breath << ", 心跳=" << heartbeat << endl;
            } else {
                cerr << "无法打开生理数据文件进行写入" << endl;
            }
        }
        
        // 每20秒更新一次
        std::this_thread::sleep_for(std::chrono::seconds(20));
    }
}

// 新增：处理生理数据请求
bool HandleGetPhysioData(int socket) {
    // 从文件读取生理数据
    ifstream dataFile(PHYSIO_DATA);
    if (!dataFile.is_open()) {
        cerr << "无法打开生理数据文件" << endl;
        return false;
    }

    // 读取数据
    getline(dataFile, breathStr);
    getline(dataFile, heartbeatStr);
    dataFile.close();

    // 转换为数值
    int breath = 16;  // 默认值
    int heartbeat = 72;
    try {
        breath = stoi(breathStr);
        heartbeat = stoi(heartbeatStr);
    } catch (...) {
        cerr << "生理数据格式错误" << endl;
    }

    // 构造JSON响应
    json response = {
        {"breath", breath},
        {"heartbeat", heartbeat}
    };

    string strResponse = response.dump();
    string httpResponse = "HTTP/1.1 200 OK\r\n" +
                        SERVER_NAME +
                        "Content-Type: application/json\r\n"
                        "Content-Length: " + 
                        to_string(strResponse.size()) + 
                        "\r\n\r\n" + 
                        strResponse;

    return SendResponse(socket, httpResponse);
}

// 新增情绪监控线程函数
void EmotionMonitorThread() {
    using namespace std::chrono;
    auto lastCheck = system_clock::now();

    while (isMonitoring) {
        // 每30秒检测一次
        std::this_thread::sleep_for(seconds(1));
        auto now = system_clock::now();
        if (duration_cast<seconds>(now - lastCheck).count() < EMOTION_CHANGE_CHECK_TIME) continue;

        // 获取当前情绪
        string currentEmotion = GetEmotion();
        
        // 线程安全锁
        {
            std::lock_guard<std::mutex> lock(emotionMutex);
            
            // 检测情绪变化
            if (!currentEmotion.empty() && currentEmotion != lastEmotion) {
                // 生成时间戳（毫秒级）
                auto timestamp = duration_cast<milliseconds>(
                    system_clock::now().time_since_epoch()
                ).count();

                // 添加新记录
                json newAlert = {
                    {"timestamp", timestamp},
                    {"emotion", currentEmotion}
                };
                emotionAlerts.push_back(newAlert);

                // 更新最后情绪状态
                lastEmotion = currentEmotion;
                
                // 控制存储量（保留最近100条）
                if (emotionAlerts.size() > EMOTION_ALERTS_SIZE) {
                    emotionAlerts.erase(emotionAlerts.begin());
                }
            }
        }
        
        lastCheck = system_clock::now();
    }
}

string GetEmotion(void){
    // 打开文件
    FILE* inputFile = fopen(ACTIVE_EMOTION_PATH, "r");
    if (inputFile == NULL) {
        printf("读取情绪文件失败 \r\n");
        return "读取情绪失败";  
    }

    // 读取文件中的第一个字符
    char ch = fgetc(inputFile);
    if (ch == EOF) {
        printf("文件为空 \r\n");
        fclose(inputFile);
        return "未识别到情绪";  
    }

    // 关闭文件
    fclose(inputFile);

    // 根据第一个字符返回相应的情绪
    switch (ch) {
        case 'a':
            return "生气";
        case 'b':
            return "厌恶";
        case 'c':
            return "恐惧";
        case 'd':
            return "高兴";
        case 'e':
            return "悲伤";
        case 'f':
            return "惊讶";
        case 'g':
            return "平静";
        default:
            return "未知情绪";
    }
}

void UserChatWithGpt() {
    chat.system_content = SYSTEM_CONTENT;

    chat.session_token = SESSION_TOKEN;
    chat.model_name = MODEL_NAME;
    string usertext = vtz.get_user_voice_to_chinese(5);
    string useremotion = GetEmotion();
    string sendgptext = "用户情绪:" + useremotion + " 用户对话内容:" + usertext + 
                        "(" + "用户呼吸次数每分钟："+ breathStr + " 用户心跳次数每分钟：" + heartbeatStr + ")";
    string gptreplytext = chat.put_text_to_gpt_get_reply(sendgptext);
    vtz.get_gpt_text_to_chinese_voice(gptreplytext);

    cout << "发送内容：" << sendgptext << endl;
    cout << "GPT返还：" << gptreplytext << endl;

    string currentTime = GetCurrentTime();

    Message newMessage;
    newMessage.text = usertext + " / " + gptreplytext;
    newMessage.time = currentTime;
    newMessage.emotion = useremotion;

    chatHistory.push_back(newMessage);

    if (chatHistory.size() > CHAT_HISTORY_SIZE) {
        chatHistory.pop_front();
    }
}

bool HandleGetMessagesRequest(int socket) {
    json jsonResponse;
    jsonResponse["messages"] = json::array();

    for (const auto& msg : chatHistory) {
        json message;
        message["userText"] = msg.text.substr(0, msg.text.find(" / "));
        message["gptText"] = msg.text.substr(msg.text.find(" / ") + 3);
        message["emotion"] = msg.emotion;
        message["time"] = msg.time;
        jsonResponse["messages"].push_back(message);
    }

    string response = jsonResponse.dump();
    string httpResponse = "HTTP/1.1 200 OK\r\n" +
                          SERVER_NAME +
                          "Date: " + GetCurrentTime() +
                          "Content-Type: application/json\r\n" +
                          "Content-Length: " + to_string(response.size()) + "\r\n\r\n" +
                          response;

    cout << "get msg respone: " << httpResponse << endl;

    return SendResponse(socket, httpResponse);
}

// 新增情绪告警处理函数
bool HandleGetEmotionAlerts(int socket) {
    std::lock_guard<std::mutex> lock(emotionMutex);
    
    json response;
    response["alerts"] = json::array();
    
    // 转换时间戳格式
    for (auto& alert : emotionAlerts) {
        json formattedAlert = {
            {"timestamp", alert["timestamp"]},
            {"emotion", alert["emotion"]}
        };
        response["alerts"].push_back(formattedAlert);
    }

    string strResponse = response.dump();
    string httpResponse = "HTTP/1.1 200 OK\r\n" +
                          SERVER_NAME +
                          "Content-Type: application/json\r\n"
                          "Content-Length: " + 
                          to_string(strResponse.size()) + 
                          "\r\n\r\n" + 
                          strResponse;

    return SendResponse(socket, httpResponse);
}

bool HandlePostRequest(string uri) {
    if (uri == "/OpenRcd") {
        cout << "OpenRcd" << endl;
        thread userChatThread(UserChatWithGpt);
        userChatThread.detach();
        return true;
    } else if (uri == "/CloseRcd") {
        cout << "CloseRcd" << endl;
        return true;
    } else {
        cout << "未知请求：" << uri << endl;
        return false;
    }
}

bool HandleRequest(int socket) {
    char buffer[8192];
    ssize_t bytesReceived = recv(socket, buffer, sizeof(buffer), 0);
    if (bytesReceived <= 0) return false;

    string request(buffer, bytesReceived);
    string method, uri, version;
    istringstream iss(request);
    if (!(iss >> method >> uri >> version)) {
        cerr << "Invalid request line" << endl;
        return false;
    }

    if (method != "GET" && method != "POST") {
        cerr << "Unsupported method: " << method << endl;
        return false;
    }

    if (uri.empty() || uri == "/") {
        uri = "/index.html";
    }

    cout << "receive method: " << method << " uri: " << uri << endl;

    if (method == "POST") {
        return HandlePostRequest(uri);
    }

    // 新增GET请求路由
    if (uri == "/getMessages") {
        return HandleGetMessagesRequest(socket);
    }
    if (uri == "/getEmotionAlerts") {  // 新增情绪告警接口
        return HandleGetEmotionAlerts(socket);
    }
    if (uri == "/getVitalData") {  // 新增生理数据接口
        return HandleGetPhysioData(socket);
    }

    string filePath = "./" + uri;
    ifstream file(filePath, ios::binary);
    if (!file) {
        cerr << "File not found: " << filePath << endl;
        return false;
    }

    file.seekg(0, ios::end);
    size_t fileSize = file.tellg();
    file.seekg(0, ios::beg);

    string contentType = GetContentType(uri);

    string response = "HTTP/1.1 200 OK\r\n" + SERVER_NAME + "Date: " + GetCurrentTime() + contentType +
                      "Content-Length: " + to_string(fileSize) + "\r\n\r\n";

    if (!SendResponse(socket, response)) return false;

    char fileBuffer[1024];
    while (fileSize > 0) {
        size_t bytesToRead = min(fileSize, static_cast<size_t>(1024));
        file.read(fileBuffer, bytesToRead);
        if (!SendResponse(socket, string(fileBuffer, bytesToRead))) return false;
        fileSize -= bytesToRead;
    }

    return true;
}

// 初始化
void InitProcess(){
    char cmd[50];
    memset(cmd, 0, sizeof(cmd));
    sprintf(cmd, "echo 'g' | cat > %s", ACTIVE_EMOTION_PATH);
    cout << cmd << endl;
    system(cmd);
}

int main(int argc, char* argv[]) {
    // 初始化
    InitProcess();
    // 启动情绪监控线程
    std::thread monitorThread(EmotionMonitorThread);
    monitorThread.detach();

    // 启动生理数据更新线程
    std::thread physioUpdateThread(UpdatePhysioDataToFile);
    physioUpdateThread.detach();

    int port = 8080;
    if (argc == 2) {
        port = stoi(argv[1]);
    }

    int serverSock = ServerSocketInit(port);
    listen(serverSock, 10);

    while (true) {
        struct sockaddr_in clientAddr;
        socklen_t addrLen = sizeof(clientAddr);
        int clientSock = accept(serverSock, (struct sockaddr*)&clientAddr, &addrLen);
        if (clientSock < 0) {
            perror("Failed to accept connection from client!");
            continue;
        }

        if (!HandleRequest(clientSock)) {
            cerr << "Failed to handle request" << endl;
        }

        close(clientSock);
    }

    // 程序结束时清理
    isMonitoring = false;
    isPhysioUpdateRunning = false;

    close(serverSock);
    return 0;
}